﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Tridion.ContentManager.CoreService.Client;
using TridionDesktopTools.Core;

namespace TridionDesktopTools.ComponentTransformer
{
    public partial class MainWindow
    {
        public TridionObjectInfo SourceTridionObject { get; set; }
        public TridionObjectInfo TargetTridionFolder { get; set; }
        public TridionSelectorMode SourceTridionSelectorMode { get; set; }
        public TridionSelectorMode TargetTridionSelectorMode { get; set; }
        public List<FieldMappingInfo> FieldMapping { get; set; }

        public MainWindow()
        {
            InitializeComponent();

            this.cbBindingType.ItemsSource = Enum.GetNames(typeof(BindingType));
            this.cbBindingType.Text = Functions.GetFromIsolatedStorage("BindingType");
            if(String.IsNullOrEmpty(this.cbBindingType.Text))
                this.cbBindingType.SelectedIndex = 0;

            //get from isolated stoage
            this.txtHost.Text = Functions.GetFromIsolatedStorage("Host");
            this.txtUsername.Text = Functions.GetFromIsolatedStorage("Username");
            this.txtPassword.Password = Functions.GetFromIsolatedStorage("Password");

            this.SourceTridionSelectorMode = TridionSelectorMode.FolderAndComponent;
            this.TargetTridionSelectorMode = TridionSelectorMode.Folder;
        }

        private void btnConnect_Click(object sender, RoutedEventArgs e)
        {
            Functions.ResetClient();

            Functions.ClientBindingType = (BindingType)Enum.Parse(typeof(BindingType), this.cbBindingType.Text);
            Functions.SaveToIsolatedStorage("BindingType", this.cbBindingType.Text);

            if (!Functions.EnsureValidClient(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password))
                return;

            this.lblSourceTridionObject.Visibility = Visibility.Visible;
            this.treeSourceTridionObject.Visibility = Visibility.Visible;
            this.lblTargetTridionFolder.Visibility = Visibility.Visible;
            this.treeTargetTridionFolder.Visibility = Visibility.Visible;

            this.SourceTridionObject = new TridionObjectInfo();

            string sourceItemTcmId = Functions.GetFromIsolatedStorage(this.txtHost.Text + "_SourceItemTcmId");
            if (!String.IsNullOrEmpty(sourceItemTcmId))
            {
                this.SourceTridionObject.TcmId = sourceItemTcmId;
            }

            string sourceItemTcmIdPath = Functions.GetFromIsolatedStorage(this.txtHost.Text + "_SourceItemTcmIdPath");
            if (!String.IsNullOrEmpty(sourceItemTcmIdPath))
            {
                this.SourceTridionObject.TcmIdPath = sourceItemTcmIdPath.Split(';').ToList();
            }

            this.TargetTridionFolder = new TridionObjectInfo();

            string targetItemTcmId = Functions.GetFromIsolatedStorage(this.txtHost.Text + "_TargetItemTcmId");
            if (!String.IsNullOrEmpty(targetItemTcmId))
            {
                this.TargetTridionFolder.TcmId = targetItemTcmId;
            }

            string targetItemTcmIdPath = Functions.GetFromIsolatedStorage(this.txtHost.Text + "_TargetItemTcmIdPath");
            if (!String.IsNullOrEmpty(targetItemTcmIdPath))
            {
                this.TargetTridionFolder.TcmIdPath = targetItemTcmIdPath.Split(';').ToList();
            }

            List<ItemInfo> publications1 = Functions.GetPublications(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password);
            this.treeSourceTridionObject.ItemsSource = publications1.Expand(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionSelectorMode, this.SourceTridionObject.TcmIdPath, this.SourceTridionObject.TcmId).MakeExpandable();

            List<ItemInfo> publications2 = Functions.GetPublications(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password);
            this.treeTargetTridionFolder.ItemsSource = publications2.Expand(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.TargetTridionSelectorMode, this.TargetTridionFolder.TcmIdPath, this.TargetTridionFolder.TcmId).MakeExpandable();

            if (publications1 != null && publications1.Count > 0 && publications2 != null && publications2.Count > 0)
            {
                //save to isolated stoage
                Functions.SaveToIsolatedStorage("Host", this.txtHost.Text);
                Functions.SaveToIsolatedStorage("Username", this.txtUsername.Text);
                Functions.SaveToIsolatedStorage("Password", this.txtPassword.Password);
            }
        }

        private void treeSourceTridionObject_Expanded(object sender, RoutedEventArgs e)
        {
            ItemInfo item = ((TreeViewItem)e.OriginalSource).DataContext as ItemInfo;
            if (item == null)
                return;

            Functions.OnItemExpanded(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, item, this.SourceTridionSelectorMode);
        }

        private void treeTargetTridionFolder_Expanded(object sender, RoutedEventArgs e)
        {
            ItemInfo item = ((TreeViewItem)e.OriginalSource).DataContext as ItemInfo;
            if (item == null)
                return;

            Functions.OnItemExpanded(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, item, this.TargetTridionSelectorMode);
        }

        private void treeSourceTridionObject_Selected(object sender, RoutedEventArgs e)
        {
            ItemInfo item = ((TreeViewItem)e.OriginalSource).DataContext as ItemInfo;
            if (item == null)
                return;

            this.SourceTridionObject.TcmId = item.TcmId;

            Functions.SaveToIsolatedStorage(this.txtHost.Text + "_SourceItemTcmId", item.TcmId);

            List<ItemInfo> list = new List<ItemInfo>();
            Functions.AddPathItem(list, item);

            this.SourceTridionObject.TcmIdPath = list.Select(x => x.TcmId).ToList();

            Functions.SaveToIsolatedStorage(this.txtHost.Text + "_SourceItemTcmIdPath", String.Join(";", this.SourceTridionObject.TcmIdPath));

            List<ItemInfo> schemas = Functions.GetSchemas(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, Functions.GetPublicationTcmId(item.TcmId)).OrderBy(x => x.Title).ToList();

            list.Reverse();
            this.SourceTridionObject.NamedPath = string.Join("/", list.Select(x => x.Title));

            if (schemas.Count > 0)
            {
                this.cbSourceSchema.ItemsSource = schemas;
                this.cbSourceSchema.DisplayMemberPath = "Title";

                string sourceSchemaTcmId = Functions.GetFromIsolatedStorage(this.txtHost.Text + "_SourceSchemaTcmId");
                if (!String.IsNullOrEmpty(sourceSchemaTcmId))
                {
                    this.cbSourceSchema.SelectedIndex = schemas.FindIndex(x => x.TcmId == sourceSchemaTcmId);
                }
            }

            this.lblSourceSchema.Visibility = Visibility.Visible;
            this.cbSourceSchema.Visibility = Visibility.Visible;
        }

        private void treeTargetTridionFolder_Selected(object sender, RoutedEventArgs e)
        {
            ItemInfo item = ((TreeViewItem)e.OriginalSource).DataContext as ItemInfo;
            if (item == null)
                return;

            this.TargetTridionFolder.TcmId = item.TcmId;

            Functions.SaveToIsolatedStorage(this.txtHost.Text + "_TargetItemTcmId", item.TcmId);

            List<ItemInfo> list = new List<ItemInfo>();
            Functions.AddPathItem(list, item);

            this.TargetTridionFolder.TcmIdPath = list.Select(x => x.TcmId).ToList();

            Functions.SaveToIsolatedStorage(this.txtHost.Text + "_TargetItemTcmIdPath", String.Join(";", this.TargetTridionFolder.TcmIdPath));

            List<ItemInfo> schemas = Functions.GetSchemas(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, Functions.GetPublicationTcmId(item.TcmId)).OrderBy(x => x.Title).ToList();

            list.Reverse();
            this.TargetTridionFolder.NamedPath = string.Join("/", list.Select(x => x.Title));

            if (schemas.Count > 0)
            {
                this.cbTargetSchema.ItemsSource = schemas;
                this.cbTargetSchema.DisplayMemberPath = "Title";

                string targetSchemaTcmId = Functions.GetFromIsolatedStorage(this.txtHost.Text + "_TargetSchemaTcmId");
                if (!String.IsNullOrEmpty(targetSchemaTcmId))
                {
                    this.cbTargetSchema.SelectedIndex = schemas.FindIndex(x => x.TcmId == targetSchemaTcmId);
                }
            }

            this.lblTargetSchema.Visibility = Visibility.Visible;
            this.cbTargetSchema.Visibility = Visibility.Visible;
        }
        
        private void treeSourceTridionObject_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ItemInfo item = this.treeSourceTridionObject.SelectedItem as ItemInfo;
            if (item == null)
                return;

            if (item.ItemType == ItemType.Folder)
            {
                Process.Start(string.Format("http://{0}/SDL/#app=wcm&entry=cme&url=%23locationId%3Dtcm%3A{1}", this.txtHost.Text, item.TcmId.Replace("tcm:", "")));
            }
            else
            {
                Process.Start(string.Format("http://{0}/WebUI/item.aspx?tcm={1}#id={2}", this.txtHost.Text, (int)item.ItemType, item.TcmId));
            }
        }

        private void treeTargetTridionFolder_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ItemInfo item = this.treeTargetTridionFolder.SelectedItem as ItemInfo;
            if (item == null)
                return;

            Process.Start(string.Format("http://{0}/SDL/#app=wcm&entry=cme&url=%23locationId%3Dtcm%3A{1}", this.txtHost.Text, item.TcmId.Replace("tcm:", "")));
        }

        private void cbSourceSchema_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ItemInfo sourceSchema = cbSourceSchema.SelectedValue as ItemInfo;
            if (sourceSchema == null)
                return;

            Functions.SaveToIsolatedStorage(this.txtHost.Text + "_SourceSchemaTcmId", sourceSchema.TcmId);

            if (this.cbSourceSchema.SelectedIndex > -1 && this.cbTargetSchema.SelectedIndex > -1)
            {
                this.btnFieldMapping.Visibility = Visibility.Visible;
                this.spButtons.Visibility = Visibility.Visible;
            }
        }

        private void cbTargetSchema_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ItemInfo targetSchema = cbTargetSchema.SelectedValue as ItemInfo;
            if (targetSchema == null)
                return;

            Functions.SaveToIsolatedStorage(this.txtHost.Text + "_TargetSchemaTcmId", targetSchema.TcmId);

            if (this.cbSourceSchema.SelectedIndex > -1 && this.cbTargetSchema.SelectedIndex > -1)
            {
                this.btnFieldMapping.Visibility = Visibility.Visible;
                this.spButtons.Visibility = Visibility.Visible;
            }
        }

        private void btnFieldMapping_Click(object sender, RoutedEventArgs e)
        {
            ItemInfo sourceSchema = cbSourceSchema.SelectedValue as ItemInfo;
            ItemInfo targetSchema = cbTargetSchema.SelectedValue as ItemInfo;

            if (sourceSchema == null || targetSchema == null)
                return;

            FieldMappingWindow dialog = new FieldMappingWindow();
            dialog.Host = this.txtHost.Text;
            dialog.Username = this.txtUsername.Text;
            dialog.Password = this.txtPassword.Password;
            dialog.SourceSchemaUri = sourceSchema.TcmId;
            dialog.TargetSchemaUri = targetSchema.TcmId;
            bool res = dialog.ShowDialog() == true;
            if (res)
            {
                this.FieldMapping = dialog.FieldMapping;

                foreach (FieldMappingInfo mapping in this.FieldMapping)
                {
                    mapping.TargetFolderUri = this.TargetTridionFolder.TcmId;
                }
            }
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            ItemInfo sourceSchema = cbSourceSchema.SelectedValue as ItemInfo;
            ItemInfo targetSchema = cbTargetSchema.SelectedValue as ItemInfo;

            if (sourceSchema == null || targetSchema == null)
                return;

            List<ResultInfo> results = new List<ResultInfo>();

            ItemType itemType = Functions.GetItemType(this.SourceTridionObject.TcmId);

            string sourceFolderTcmId = itemType == ItemType.Folder ? this.SourceTridionObject.TcmId : Functions.GetItemFolder(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionObject.TcmId);

            //same folder selected: schema change and component fix functionality
            if (sourceFolderTcmId == this.TargetTridionFolder.TcmId)
            {
                if (itemType == ItemType.Component && sourceSchema.TcmId == targetSchema.TcmId)
                {
                    // fix single component
                    Functions.FixComponent(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionObject.TcmId, sourceSchema.TcmId, this.FieldMapping, results);
                }
                else if (itemType == ItemType.Component)
                {
                    // change schema for single component
                    Functions.ChangeSchemaForComponent(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionObject.TcmId, sourceSchema.TcmId, targetSchema.TcmId, this.FieldMapping, results);
                }
                else if (sourceSchema.TcmId == targetSchema.TcmId)
                {
                    // fix all componnets in folder
                    Functions.FixComponents(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionObject.TcmId, true, sourceSchema.TcmId, this.FieldMapping, results);
                }
                else
                {
                    // change schema for all components in folder
                    Functions.ChangeSchemasForComponentsInFolder(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionObject.TcmId, true, sourceSchema.TcmId, targetSchema.TcmId, this.FieldMapping, results);
                }
            }
            else if (itemType == ItemType.Component)
            {
                // move / transform component
                Functions.TransformComponent(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionObject.TcmId, this.TargetTridionFolder.TcmId, sourceSchema.TcmId, targetSchema.TcmId, this.FieldMapping, results);
            }
            else
            {
                // move / transform all components in folder
                Functions.TransformComponentsFromFolder(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionObject.TcmId, true, this.TargetTridionFolder.TcmId, sourceSchema.TcmId, targetSchema.TcmId, this.FieldMapping, results);
            }

            if (results.Any(x => x.Status == Status.Success))
            {
                ResultInfo resultFinish = new ResultInfo();
                resultFinish.Status = Status.Info;
                resultFinish.Message = "Finished";
                results.Add(resultFinish);
            }

            //show results
            ResultsWindow dialog = new ResultsWindow();
            dialog.ListBoxReport.ItemsSource = results;
            dialog.ListBoxReport.MouseDoubleClick += lbReport_OnMouseDoubleClick;
            dialog.Show();

            //reload source and target tree
            List<ItemInfo> publications1 = Functions.GetPublications(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password);
            this.treeSourceTridionObject.ItemsSource = publications1.Expand(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.SourceTridionSelectorMode, this.SourceTridionObject.TcmIdPath, this.SourceTridionObject.TcmId).MakeExpandable();

            List<ItemInfo> publications2 = Functions.GetPublications(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password);
            this.treeTargetTridionFolder.ItemsSource = publications2.Expand(this.txtHost.Text, this.txtUsername.Text, this.txtPassword.Password, this.TargetTridionSelectorMode, this.TargetTridionFolder.TcmIdPath, this.TargetTridionFolder.TcmId).MakeExpandable();
        }

        private void btnOk_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void lbReport_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ListBox listBox = sender as ListBox;
            if (listBox == null)
                return;

            ResultInfo item = listBox.SelectedItem as ResultInfo;
            if (item == null)
                return;

            ItemType itemType = Functions.GetItemType(item.TcmId);

            if (itemType == ItemType.Folder || itemType == ItemType.StructureGroup)
            {
                Process.Start(string.Format("http://{0}/SDL/#app=wcm&entry=cme&url=%23locationId%3Dtcm%3A{1}", this.txtHost.Text, item.TcmId.Replace("tcm:", "")));
            }
            else
            {
                Process.Start(string.Format("http://{0}/WebUI/item.aspx?tcm={1}#id={2}", this.txtHost.Text, (int)item.ItemType, item.TcmId));
            }
        }

    }
}
